#ifndef _DBL_RAKNETCLIENT_H
#define _DBL_RAKNETCLIENT_H

#include "../RakNetSources/RakPeerInterface.h"
#include "../RakNetSources/BitStream.h"
#include <functional>

class raknet_client {
    using connect_cb = std::function<void(bool, void*)>;
    using disconnect_cb = std::function<void(void*)>;
    using recv_cb = std::function<bool(unsigned char, unsigned char*, int, void*)>;
public:
    raknet_client();
    ~raknet_client();

    inline void set_callback(connect_cb on_conn, disconnect_cb on_dis, recv_cb on_recv)
    {
      on_conn_ = on_conn;
      on_dis_ = on_dis;
      on_recv_ = on_recv;
    }
    inline void set_data(void* usr_data)
    {
      usr_data_ = usr_data;
    }

public:
    bool connect(const char* host, unsigned short port, char* password = 0, unsigned short client_port = 0);
    void send(RakNet::MessageID cmd, const unsigned char* pkg, int length)
    {
      RakNet::BitStream bits(sizeof(cmd) + length);
      bits.Write(cmd);
      bits.Write((const char*)pkg, length);

      peer_->Send(&bits, HIGH_PRIORITY, RELIABLE_ORDERED, 0, RakNet::UNASSIGNED_SYSTEM_ADDRESS, true);
    }

private:
    void run();

private:
    RakNet::RakPeerInterface* peer_;
    void* usr_data_;

    connect_cb on_conn_;
    disconnect_cb on_dis_;
    recv_cb on_recv_;
}; // raknet_client

inline raknet_client& get_client()
{
  static raknet_client mgr;
  return mgr;
}

#endif // _DBL_RAKNETCLIENT_H
